// VCD Simple PropertyDlg.cpp : implementation file
//

#include "stdafx.h"
#include "VCD Simple Property.h"
#include "VCD Simple PropertyDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CVCDSimplePropertyDlg dialog

CVCDSimplePropertyDlg::CVCDSimplePropertyDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CVCDSimplePropertyDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CVCDSimplePropertyDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CVCDSimplePropertyDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CVCDSimplePropertyDlg)
		// NOTE: the ClassWizard will add DDX and DDV calls here
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CVCDSimplePropertyDlg, CDialog)
	//{{AFX_MSG_MAP(CVCDSimplePropertyDlg)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_EXPOSURE_AUTO, OnExposureAuto)
	ON_BN_CLICKED(IDC_GAIN_AUTO, OnGainAuto)
	ON_BN_CLICKED(IDC_WB_AUTO, OnWbAuto)
	ON_BN_CLICKED(IDC_WB_ONEPUSH, OnWbOnepush)
	ON_WM_HSCROLL()
	//}}AFX_MSG_MAP
	ON_WM_TIMER()
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CVCDSimplePropertyDlg message handlers

using namespace DShowLib;

int AbsValToSliderPosMapped( DShowLib::tIVCDAbsoluteValuePropertyPtr itf, double val, int sliderSteps, double map(double) )
{
	double range_min = itf->getRangeMin();
	double range_max = itf->getRangeMax();	

	double mapped_min = map( range_min );
	double mapped_max = map( range_max );
	double mapped_val = map( val );

	double mapped_range = mapped_max - mapped_min;
	double mapped_offset = mapped_val - mapped_min;	

	return (int)(sliderSteps * mapped_offset / mapped_range + 0.5);
}

double SliderPosToAbsValMapped( DShowLib::tIVCDAbsoluteValuePropertyPtr itf, int pos, int sliderSteps, double map( double ), double unmap( double ) )
{
	double range_min = itf->getRangeMin();
	double range_max = itf->getRangeMax();

	double mapped_min = map( range_min );
	double mapped_max = map( range_max );

	double mapped_range = mapped_max - mapped_min;
	
	double mapped_val = mapped_min + mapped_range * pos / sliderSteps;

	return unmap( mapped_val );
}

int AbsValToSliderPosLogarithmic( DShowLib::tIVCDAbsoluteValuePropertyPtr itf, double val, int sliderSteps )
{
	return AbsValToSliderPosMapped( itf, val, sliderSteps, std::log );
}

double SliderPosToAbsValLogarithmic( DShowLib::tIVCDAbsoluteValuePropertyPtr itf, int pos, int sliderSteps )
{
	return SliderPosToAbsValMapped( itf, pos, sliderSteps, std::log, std::exp );
}

double identity( double x )
{
	return x;
}

int AbsValToSliderPosLinear( DShowLib::tIVCDAbsoluteValuePropertyPtr itf, double val, int sliderSteps )
{
	return AbsValToSliderPosMapped( itf, val, sliderSteps, identity );
}

double SliderPosToAbsValLinear( DShowLib::tIVCDAbsoluteValuePropertyPtr itf, int pos, int sliderSteps )
{
	return SliderPosToAbsValMapped( itf, pos, sliderSteps, identity, identity );
}

//<<oninit
BOOL CVCDSimplePropertyDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

	// Get references to the controls
	m_pExposureSlider = (CSliderCtrl*)GetDlgItem( IDC_EXPOSURE_SLIDER );	
	m_pExposureStatic = (CStatic*)GetDlgItem( IDC_EXPOSURE_STATIC );
	m_pExposureAutoCheck = (CButton*)GetDlgItem( IDC_EXPOSURE_AUTO );

	m_pGainSlider = (CSliderCtrl*)GetDlgItem( IDC_GAIN_SLIDER );
	m_pGainStatic = (CStatic*)GetDlgItem( IDC_GAIN_STATIC );
	m_pGainAutoCheck = (CButton*)GetDlgItem( IDC_GAIN_AUTO );
	
	m_pWbRedSlider = (CSliderCtrl*)GetDlgItem( IDC_WBRED_SLIDER );
	m_pWbRedStatic = (CStatic*)GetDlgItem( IDC_WBRED_STATIC );
	m_pWbGreenSlider = (CSliderCtrl*)GetDlgItem( IDC_WBGREEN_SLIDER );
	m_pWbGreenStatic = (CStatic*)GetDlgItem( IDC_WBGREEN_STATIC );
	m_pWbBlueSlider = (CSliderCtrl*)GetDlgItem( IDC_WBBLUE_SLIDER );
	m_pWbBlueStatic = (CStatic*)GetDlgItem( IDC_WBBLUE_STATIC );
	m_pWbAutoCheck = (CButton*)GetDlgItem( IDC_WB_AUTO );
	m_pWbOnePushButton = (CButton*)GetDlgItem( IDC_WB_ONEPUSH );

	// Get exposure absolute value and auto interfaces
	m_pExposureAbsolute = m_Grabber.getVCDPropertyInterface<DShowLib::IVCDAbsoluteValueProperty>( VCDID_Exposure, VCDElement_Value );
	m_pExposureAuto = m_Grabber.getVCDPropertyInterface<DShowLib::IVCDSwitchProperty>( VCDID_Exposure, VCDElement_Auto );

	// Get gain absolute value and auto interfaces
	m_pGainAbsolute = m_Grabber.getVCDPropertyInterface<DShowLib::IVCDAbsoluteValueProperty>( VCDID_Gain, VCDElement_Value );
	m_pGainAuto = m_Grabber.getVCDPropertyInterface<DShowLib::IVCDSwitchProperty>( VCDID_Gain, VCDElement_Auto );

	// Get white balance red range, green range, blue range, auto and one push interfaces
	m_pWBRedRange = m_Grabber.getVCDPropertyInterface<DShowLib::IVCDRangeProperty>( VCDID_WhiteBalance, VCDElement_WhiteBalanceRed );
	m_pWBGreenRange = m_Grabber.getVCDPropertyInterface<DShowLib::IVCDRangeProperty>( VCDID_WhiteBalance, VCDElement_WhiteBalanceGreen );
	m_pWBBlueRange = m_Grabber.getVCDPropertyInterface<DShowLib::IVCDRangeProperty>( VCDID_WhiteBalance, VCDElement_WhiteBalanceBlue );
	m_pWBAuto = m_Grabber.getVCDPropertyInterface<DShowLib::IVCDSwitchProperty>( VCDID_WhiteBalance, VCDElement_Auto );
	m_pWBOnePush = m_Grabber.getVCDPropertyInterface<DShowLib::IVCDButtonProperty>( VCDID_WhiteBalance, VCDElement_OnePush );

	// Initialize exposure auto
	if( m_pExposureAuto == 0 )
	{
		m_pExposureAutoCheck->EnableWindow( FALSE );
	}
	else
	{
		if( m_pExposureAuto->getSwitch() )
		{
			m_pExposureAutoCheck->SetCheck( BST_CHECKED );
			m_pExposureSlider->EnableWindow( FALSE );
		}
		else
		{
			m_pExposureAutoCheck->SetCheck( BST_UNCHECKED );
		}
	}

	// Initialize exposure value
	if( m_pExposureAbsolute != 0 )
	{
		int rangeMin = 0;
		int rangeMax = 100;
		int rangePos = AbsValToSliderPosLogarithmic( m_pExposureAbsolute, m_pExposureAbsolute->getValue(), 100 );

		m_pExposureSlider->SetRange( rangeMin, rangeMax );
		m_pExposureSlider->SetPos( rangePos );

		CString s;
		s.Format( TEXT( "%g" ), m_pExposureAbsolute->getValue() );
		m_pExposureStatic->SetWindowText( s );
	}

	// Initialize gain auto
	if( m_pGainAuto == 0 )
	{
		m_pGainAutoCheck->EnableWindow( FALSE );
	}
	else
	{
		if( m_pGainAuto->getSwitch() )
		{
			m_pGainAutoCheck->SetCheck( BST_CHECKED );
			m_pGainSlider->EnableWindow( FALSE );
		}
		else
		{
			m_pGainAutoCheck->SetCheck( BST_UNCHECKED );
		}
	}

	// Initialize gain value
	if( m_pGainAbsolute != 0 )
	{
		int rangeMin = 0;
		int rangeMax = 100;
		int rangePos = AbsValToSliderPosLinear( m_pGainAbsolute, m_pGainAbsolute->getValue(), 100 );

		m_pGainSlider->SetRange( rangeMin, rangeMax );
		m_pGainSlider->SetPos( rangePos );

		CString s;
		s.Format( TEXT( "%g" ), m_pGainAbsolute->getValue() );
		m_pGainStatic->SetWindowText( s );
	}
	
	if( m_pWBAuto == 0 )
	{
		m_pWbAutoCheck->EnableWindow( FALSE );
	}
	else
	{
		m_pWbAutoCheck->SetCheck( m_pWBAuto->getSwitch() ? BST_CHECKED : BST_UNCHECKED );

		m_pWbRedSlider->EnableWindow( !m_pWBAuto->getSwitch() );
		m_pWbGreenSlider->EnableWindow( !m_pWBAuto->getSwitch() );
		m_pWbBlueSlider->EnableWindow( !m_pWBAuto->getSwitch() );
	}

	if( m_pWBRedRange != 0 )
	{
		m_pWbRedSlider->SetRange( m_pWBRedRange->getRangeMin(), m_pWBRedRange->getRangeMax() );
		m_pWbRedSlider->SetPos( m_pWBRedRange->getValue() );

		CString s;
		s.Format( TEXT( "%d" ), m_pWBRedRange->getValue() );
		m_pWbRedStatic->SetWindowText( s );
	}
	if( m_pWBGreenRange != 0 )
	{
		m_pWbGreenSlider->SetRange( m_pWBGreenRange->getRangeMin(), m_pWBGreenRange->getRangeMax() );
		m_pWbGreenSlider->SetPos( m_pWBGreenRange->getValue() );

		CString s;
		s.Format( TEXT( "%d" ), m_pWBGreenRange->getValue() );
		m_pWbGreenStatic->SetWindowText( s );
	}
	if( m_pWBBlueRange != 0 )
	{
		m_pWbBlueSlider->SetRange( m_pWBBlueRange->getRangeMin(), m_pWBBlueRange->getRangeMax() );
		m_pWbBlueSlider->SetPos( m_pWBBlueRange->getValue() );

		CString s;
		s.Format( TEXT( "%d" ), m_pWBBlueRange->getValue() );
		m_pWbBlueStatic->SetWindowText( s );
	}

	if( m_pWBOnePush == 0)
	{
		m_pWbOnePushButton->EnableWindow( FALSE );
	}

	// Set output window for live mode
	m_Grabber.setHWND( GetDlgItem( IDC_DISPLAY )->GetSafeHwnd() );
	// Start live mode
	m_Grabber.startLive();

	SetTimer( 0, 250, 0 );
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}
//>>

//////////////////////////////////////////////////////////////////////////
/*! Let the user select a device and make initial settings
*/
//<<selectdevice
bool CVCDSimplePropertyDlg::selectDevice()
{
	m_Grabber.showDevicePage( m_hWnd );

	return m_Grabber.isDevValid();
}
//>>

//The checkboxes' event handlers
//<<brightness_click
void CVCDSimplePropertyDlg::OnExposureAuto() 
{
	if( m_pExposureAutoCheck->GetCheck() )
	{
		m_pExposureAuto->setSwitch( true );
		m_pExposureSlider->EnableWindow( FALSE );
	}
	else
	{
		m_pExposureAuto->setSwitch( false );
		m_pExposureSlider->EnableWindow();
	}	
}
//>>

void CVCDSimplePropertyDlg::OnGainAuto()
{
	if( m_pGainAutoCheck->GetCheck() )
	{
		m_pGainAuto->setSwitch( true );
		m_pGainSlider->EnableWindow( FALSE );
	}
	else
	{
		m_pGainAuto->setSwitch( false );
		m_pGainSlider->EnableWindow();
	}
}

void CVCDSimplePropertyDlg::OnWbAuto() 
{
	if( m_pWbAutoCheck->GetCheck() )
	{
		m_pWBAuto->setSwitch( true );		
		m_pWbRedSlider->EnableWindow( FALSE );
		m_pWbGreenSlider->EnableWindow( FALSE );
		m_pWbBlueSlider->EnableWindow( FALSE );
		m_pWbOnePushButton->EnableWindow( FALSE );
	}
	else
	{
		m_pWBAuto->setSwitch( false );
		m_pWbRedSlider->EnableWindow();
		m_pWbGreenSlider->EnableWindow();
		m_pWbBlueSlider->EnableWindow();		
		m_pWbOnePushButton->EnableWindow();
	}
}

// Button event handler
//<<button_click
void CVCDSimplePropertyDlg::OnWbOnepush() 
{
	m_wbOnePushUpdateCount = 0;
	m_pWBOnePush->push();
}
//>>


// The sliders' event handler
//<<onHscroll
void CVCDSimplePropertyDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	int pos = ((CSliderCtrl*) pScrollBar)->GetPos();
	CString posText;
	posText.Format( TEXT("%d"), pos );

	// Check which slider was scrolled
	switch( pScrollBar->GetDlgCtrlID() )
	{
	case IDC_WBRED_SLIDER:
		{
			m_pWBRedRange->setValue( pos );
			m_pWbRedStatic->SetWindowText( posText );
		}
		break;
	case IDC_WBGREEN_SLIDER:
		{
			m_pWBGreenRange->setValue( pos );
			m_pWbGreenStatic->SetWindowText( posText );
		}
		break;
	case IDC_WBBLUE_SLIDER:
		{
			m_pWBBlueRange->setValue( pos );
			m_pWbBlueStatic->SetWindowText( posText );
		}
		break;
	case IDC_EXPOSURE_SLIDER:
		{
			double val = SliderPosToAbsValLogarithmic( m_pExposureAbsolute, pos, 100 );
			m_pExposureAbsolute->setValue( val );

			posText.Format( TEXT( "%g %s" ), val, m_pExposureAbsolute->getDimTypeW().c_str() );
			m_pExposureStatic->SetWindowText( posText );
		}
		break;
	case IDC_GAIN_SLIDER:
		{
			double val = SliderPosToAbsValLinear( m_pGainAbsolute, pos, 100 );
			m_pGainAbsolute->setValue( val );

			posText.Format( TEXT( "%g %s" ), val, m_pGainAbsolute->getDimTypeW().c_str() );
			m_pGainStatic->SetWindowText( posText );
		}
		break;
	}
	
	CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
}
//>>


void CVCDSimplePropertyDlg::OnTimer( UINT_PTR nIDEvent )
{
	if( nIDEvent == 0 )
	{
		if( m_pExposureAuto->getSwitch() )
		{
			int rangePos = AbsValToSliderPosLogarithmic( m_pExposureAbsolute, m_pExposureAbsolute->getValue(), 100 );

			m_pExposureSlider->SetPos( rangePos );

			CString s;
			s.Format( TEXT( "%g %s" ), m_pExposureAbsolute->getValue(), m_pExposureAbsolute->getDimTypeW().c_str() );
			m_pExposureStatic->SetWindowText( s );
		}

		if( m_pGainAuto->getSwitch() )
		{
			int rangePos = AbsValToSliderPosLinear( m_pGainAbsolute, m_pGainAbsolute->getValue(), 100 );

			m_pGainSlider->SetPos( rangePos );

			CString s;
			s.Format( TEXT( "%g %s" ), m_pGainAbsolute->getValue(), m_pGainAbsolute->getDimTypeW().c_str() );
			m_pGainStatic->SetWindowText( s );
		}

		if( m_pWBAuto->getSwitch() || m_wbOnePushUpdateCount++ < 40 )
		{
			if( m_pWBRedRange != 0 )
			{
				m_pWbRedSlider->SetPos( m_pWBRedRange->getValue() );

				CString s;
				s.Format( TEXT( "%d" ), m_pWBRedRange->getValue() );
				m_pWbRedStatic->SetWindowText( s );
			}
			if( m_pWBGreenRange != 0 )
			{
				m_pWbGreenSlider->SetPos( m_pWBGreenRange->getValue() );

				CString s;
				s.Format( TEXT( "%d" ), m_pWBGreenRange->getValue() );
				m_pWbGreenStatic->SetWindowText( s );
			}
			if( m_pWBBlueRange != 0 )
			{
				m_pWbBlueSlider->SetPos( m_pWBBlueRange->getValue() );

				CString s;
				s.Format( TEXT( "%d" ), m_pWBBlueRange->getValue() );
				m_pWbBlueStatic->SetWindowText( s );
			}
		}
	}

	CDialog::OnTimer( nIDEvent );
}
